
#include <ConnectionBroker/TcpMessage.h>

using namespace ConnectionBroker;

TcpMessage::TcpMessage()
: body_length_(0), data_(NULL)
{
}

TcpMessage::TcpMessage(const TcpMessage& other)
: body_length_(0), data_(NULL)
{
   body_length_ = other.body_length();
   channel_ = other.channel();
   memcpy(header_, other.header(), header_length);
   if(other.data())
   {
      create_data_buffer();
      memcpy(data_, other.data(), header_length + body_length_ + 1);
   }
}

TcpMessage::~TcpMessage()
{
   if(data_)
   {
      delete [] data_;
      data_ = NULL;
   }
}

void TcpMessage::body(const char* bodyBuffer, int len)
{
   if(!data_)
      return;

   memcpy(body(), bodyBuffer, len);
   int bufferLengthMinusOne = length();
   data_[bufferLengthMinusOne] = '\0';
}

void TcpMessage::body_length(uint32_t length)
{
   body_length_ = length;
   create_data_buffer();
}

void TcpMessage::create_data_buffer()
{
   if(data_)
   {
      delete [] data_;
      data_ = NULL;
   }

   uint32_t bodyBufferLength = body_length_ + 1; //For null terminating the body.
   uint32_t dataBufferLength = header_length + bodyBufferLength;
   data_ = new char[dataBufferLength];
   memset(data_, '\0', dataBufferLength);
}

void TcpMessage::decode_header()
{
   uint32_t sz = sizeof(header_minus_ctrl_length);
   uint32_t szChannel = sizeof(channel_length);
   uint32_t nbl = 0;
   uint32_t nc = 0;
   for(uint32_t i = 0; i < sz; ++i)
      nbl |= (uint32_t)(header_[i] << ((sz - 1 - i) * 8));
   for(uint32_t i = sz; i < sz + szChannel; ++i)
      nc |= (uint32_t)(header_[i] << ((sz - 1 - i) * 8));

   body_length(ntohl(nbl));
   channel_ = ntohl(nc);

   memcpy(data_, header_, header_length);
}

void TcpMessage::encode_header()
{
   if(!data_)
      return;

   uint32_t sz = sizeof(header_minus_ctrl_length);
   uint32_t szChannel = sizeof(channel_length);
   uint32_t nbl = htonl(body_length_);
   uint32_t nc = htonl(channel_);
   for(uint32_t i = 0; i < sz; ++i)
      data_[i] = (nbl >> ((sz - 1 - i) * 8)) & 0xFF;
   for(uint32_t i = sz; i < sz + szChannel; ++i)
      data_[i] = (nc >> ((sz - 1 - i) * 8)) & 0xFF;
}

